/***********************************************************
 * Product Name: ExcelQuicker
 * Copyright (c)2005, Eunge
 * Author: Eunge
 * Web Site: www.eudev.net
 * Mail/MSN: eudev.net@yeah.net
 * ********************************************************/
using System;
using System.Collections;
using System.IO;
using System.Text;
using System.Data;

namespace ExcelQuicker.Framework
{
	/// <summary>
	/// The class is used to output DataTable or DataGrid object to the excel document
	/// </summary>
	[Serializable]
	public abstract class EQTableBase: EQTextBase  
	{
		#region Attribution
		private DataTable mTable;
		private EQBool mInsertMode = EQBool.Default;
		private int mTableTop = DefaultInt;
		private int mTableLeft = DefaultInt;
		private EQType[] mColumnsDataType;	//Every column maps to a column data type(EQType).
		private IBatchMode mBatchModeObject = new BatchArithmetic();
		private EQChart mChart = null;

		/// <summary>
		/// Set/Get the chart object of this object
		/// </summary>
		public virtual EQChart Chart
		{
			get
			{
				return this.mChart;
			}
			set
			{
				this.mChart = value;
				this.mChart.RenderTableBase(this);
			}
		}

		/// <summary>
		/// Set/Get whether using insert mode. 
		/// If so, whatever how many rows in this object, this object will only occupy one row in the final document. 
		/// It will insert several rows into the suitable position. 
		/// It's convenient when using template mode
		/// </summary>
		public bool InsertMode
		{
			get
			{
				return EQKit.ToBool(this.mInsertMode);
			}
			set
			{
				this.mInsertMode = EQKit.ToEQBool(value);
			}
		}

		/// <summary>
		/// Get the type of columns
		/// </summary>
		public EQType[] ColumnsDataType
		{
			get
			{
				return this.mColumnsDataType;
			}
		}


		/// <summary>
		/// Set/Get the implemental object of outputing the data to excel document
		/// </summary>
		public IBatchMode BatchModeObject
		{
			get
			{
				return this.mBatchModeObject;
			}
			set
			{
				this.mBatchModeObject = value;
			}
		}

		/// <summary>
		/// Get the DataTable object of this object
		/// </summary>
		public DataTable Table
		{
			get
			{
				return this.mTable;
			}
		}


		/// <summary>
		/// Get column index of left-top cell of this object on the excel document. (Index starts from 0)
		/// </summary>
		public int TableLeft
		{
			get
			{
				return this.mTableLeft;
			}
		}


		/// <summary>
		/// Get row index of left-top cell of this object on the excel document. (Index starts from 0)
		/// </summary>
		public int TableTop
		{
			get
			{
				return this.mTableTop;
			}
		}


		/// <summary>
		/// Get the column name array of DataTable
		/// </summary>
		public string[] TableColumnsName
		{
			get
			{
				string[] strColumnName = new string[this.TableColumnsCount];
				for(int i=0; i<strColumnName.Length; i++)
					strColumnName[i] = this.Table.Columns[i].ColumnName;
				return strColumnName;
			}
		}


        /// <summary>
        /// Get amount of columns
        /// </summary>
        public int TableColumnsCount
        {
            get
            {
                return this.Table.Columns.Count;
            }
        }

        /// <summary>
        /// Get amount of rows
        /// </summary>
        public int TableRowsCount
        {
            get
            {
                return this.Table.Rows.Count;
            }
        }


		/// <summary>
		/// Get the first row index of items on the excel document. (Items mean the data in DataTable object)
		/// </summary>
		/// <example>
		/// <br>EQTable table = new EQTable(dt, 2, 3);	//Assume that there are three columns in this datatable</br>
		/// <br>string[] title = {"Name", "Age", "Career"};</br>
		/// <br>table.AddHeader(table.TableColumnsName);	//Add the column name of dt as the first row</br>
		/// <br>table.AddHeader(title);	//Add a self-defined row as the second row</br>
		/// <br>int pos = table.ItemTop;</br>
		/// <br>Try to get the first row position of items. It will be 4. Because the position of first row in EQTable is 2. We add two extra rows at the top of EQTable. So the row position of items is 4</br>
		/// </example>
		public abstract int ItemTop
		{
			get;
		}


		/// <summary>
		/// Get the first column index of items on the excel document. (Items mean the data in DataTable object)
		/// </summary>
		public abstract int ItemLeft
		{
			get;
		}
		#endregion

		/// <summary>
		/// Set the type of specialized column by its column index
		/// </summary>
		/// <param name="index"></param>
		/// <param name="type"></param>
		/// <remarks>Default type is EQType.Text</remarks>
		/// <example>
		/// <br>EQTableBase table = EQTable(dt, 1, 1);	//dt is a object of class DataTable, including three columns</br>
		/// <br>table.SetColumnDataType(1, EQType.General); //set the second column's type</br>
		/// </example>
		public void SetColumnDataType(int index, EQType type)
		{
			if(index<0 || index>=this.TableColumnsCount)
				throw new EQException("EQ1023", index.ToString(EQKit.ObjNumberFormatInfo), (this.TableColumnsCount - 1).ToString(EQKit.ObjNumberFormatInfo));

			this.ColumnsDataType[index] = type;
		}


		/// <summary>
		/// Set the type of specialized column by its column name
		/// </summary>
		/// <param name="columnName"></param>
		/// <param name="type"></param>
		/// <remarks>Default type is EQType.Text</remarks>
		/// <example>
		/// <br>EQTableBase table = EQTable(dt, 1, 1);	//dt is a object of class DataTable, including the column "Name"</br>
		/// <br>table.SetColumnDataType("Name", EQType.General)</br>
		/// </example>
		public void SetColumnDataType(string columnName, EQType type)
		{
			if(!this.Table.Columns.Contains(columnName))
				throw new EQException("EQ1024", columnName, EQKit.Concat(this.TableColumnsName));

			this.SetColumnDataType(this.Table.Columns[columnName].Ordinal, type);
		}


		/// <summary>
		///  Initialize object
		/// </summary>
		/// <param name="objDataTable"></param>
		/// <param name="top">The row index of the top-left cell</param>
		/// <param name="left">The column index of the top-left cell</param>
		protected EQTableBase(DataTable objDataTable, int top, int left)
		{
			this.mTableTop = EQKit.CheckPosition(top);
			this.mTableLeft = EQKit.CheckPosition(left);
			this.mTable = objDataTable;

			this.mColumnsDataType = new EQType[this.TableColumnsCount];
			for(int i=0; i<this.mColumnsDataType.Length; i++)
				this.mColumnsDataType[i] = EQType.Text;
		}

		/// <summary>
		/// Initialize object. In this constructor, objDataGrid.DataSource will be converted to a DataTable object and call another constructor EQTableBase(DataTable, int, int)
        /// 
		/// </summary>
		/// <param name="objDataGrid"></param>
		/// <param name="top">The row index of the top-left cell</param>
		/// <param name="left">The column index of the top-left cell</param>
		protected EQTableBase(System.Web.UI.WebControls.DataGrid objDataGrid, int top, int left)
		{
			DataTable dt = null;
			try
			{
				dt = objDataGrid.DataSource as DataTable;
			}
			catch(Exception exp)
			{
				throw new EQException("EQ1025", exp, this.GetType().ToString());
			}
			this.mTableTop = EQKit.CheckPosition(top);
			this.mTableLeft = EQKit.CheckPosition(left);
			this.mTable = dt;

			this.mColumnsDataType = new EQType[this.TableColumnsCount];
			for(int i=0; i<this.mColumnsDataType.Length; i++)
				this.mColumnsDataType[i] = EQType.Text;
		}

		/// <summary>
		/// Output chart in this object to the excel document
		/// </summary>
		/// <param name="objWorksheet"></param>
		protected internal override void Output(Excel.Worksheet objWorksheet)
		{
			if(this.mChart != null)
				this.mChart.Output(objWorksheet);
		}

	}
}
